package cn.zwx.search.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.zwx.search.SearchExampleApplication;
import cn.zwx.search.model.Sort;
import cn.zwx.search.model.req.OrderInfoReq;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

/**
 * @description: 解析传入参数
 * @projectName:search-example
 * @see:cn.zwx.search.utils
 * @author:zhangwenxue
 * @createTime:2020/10/23 17:24
 * @version:1.0
 */
public class ElasticSearchBuilderUtil {

    private static Logger logger= LoggerFactory.getLogger(SearchExampleApplication.class);

   /**
    * @description 默认分页信息
    **/
    private static final Integer DEFAULT_PAGE_SIZE = 10;

    /**
     * @description 默认分页信息
     **/
    private static final Integer DEFAULT_PAGE_NUM= 1;


    /**
     * @description （
     * 1 构建一个检索请求 （SearchRequest）。
     * （2 构建一个搜索源（SearchSourceBuilder），可以为这个对象添加搜索条件，超时时间，高亮属性等。
     * （3 构建一个高亮器（HighlightBuilder），为其指定高亮的属性以及前缀和后缀等，例如想让 “”西红柿“”这三个字高亮显示，就可以为这个关键词加前缀<span style="color:red">，后缀</span>。这样整个结果就是<span style="color:red">西红柿</span>，将来再通过html网页解析就可以实现结果高亮。
     * （4 为SearchRequest设置SearchSourceBuilder，执行检索，返回SearchResponse。
     * （5 拿到SearchResponse中的hits的hits，遍历这个hits数组，拿到之前设置的高亮字段进行拼接，再讲拼接好的值替换旧的值。
     **/
    /**
     * @description 订单查询请求参数拼装
     * @param req
     * @return org.elasticsearch.search.builder.SearchSourceBuilder
     * @author zhangwenxue
     * @createTime 2020/10/23 17:58
     **/
    public static SearchSourceBuilder getSearchSourceBuilderForOrder(OrderInfoReq req) {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        if (req.getPageNum() == null) {
            req.setPageNum(DEFAULT_PAGE_NUM);
        }

        if (req.getPageSize() == null) {
            req.setPageSize(DEFAULT_PAGE_SIZE);
        }

        // 符合条件查询
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
        //查询未删除的
        boolBuilder.must(QueryBuilders.termQuery("delFlag", 1));
        // 动态条件----keyword
        if (StrUtil.isNotBlank(req.getOrderId())) {
            boolBuilder.should(QueryBuilders.termQuery("id", req.getOrderId()));
        }
        if (StrUtil.isNotBlank(req.getGoodsId())){
            boolBuilder.should(QueryBuilders.termQuery("goodsId", req.getOrderId()));
        }
        if (StrUtil.isNotBlank(req.getGoodsName())){
            boolBuilder.should(QueryBuilders.termQuery("goodsName", req.getGoodsName()));
        }
        if (Objects.nonNull(req.getOrderState())){
            boolBuilder.should(QueryBuilders.termQuery("orderState", req.getOrderState()));
        }
        //时间拼接 范围查询
        String startTime = req.getStartTime();
        String endTime = req.getEndTime();
        if (StrUtil.isNotBlank(startTime)&&StrUtil.isNotBlank(endTime)){
            boolBuilder.must(QueryBuilders.boolQuery().should(QueryBuilders.rangeQuery("createTime").from(startTime).to(endTime)));
        }
        //查询条件设置
        sourceBuilder.query(boolBuilder);

        //结果高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //如果该属性中有多个关键字 则都高亮
        highlightBuilder.requireFieldMatch(true);
        highlightBuilder.highlighterType("unified");
        highlightBuilder.field("goodsName");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        //设置高亮此词
        sourceBuilder.highlighter(highlightBuilder);

        //计算分页信
        sourceBuilder.from((Math.multiplyExact( Math.subtractExact(req.getPageNum(),1),req.getPageSize())));
        sourceBuilder.size(req.getPageSize());
       //排序拼接
        if (CollectionUtil.isEmpty(req.getSortList())){
            String sortField ="createTime.sort";
            sourceBuilder.sort(sortField, SortOrder.DESC);
        }
        //保留得分字段
        for (Sort sort : req.getSortList()) {
            sourceBuilder.sort(sort.getField(), sort.getOrder());
        }
        sourceBuilder.sort("_score",SortOrder.DESC);
        String queryString = sourceBuilder.toString();
        logger.info("{},的查询条件拼接后为：{}", JSON.toJSONString(sourceBuilder), queryString);
        return sourceBuilder;
    }
}
